import { ITERATE_KEY, TrackOpTypes } from '../utils.js'
import { activeEffect, targetMap } from './effect.js'
let shouldTrack = true // 控制是否需要进行依赖收集的开关

/**
 * 暂停依赖收集
 */
export function pauseTracking() {
  shouldTrack = false
}

/**
 * 恢复依赖收集
 */
export function resumeTracking() {
  shouldTrack = true
}

/**
 * 收集器：用于收集依赖
 * @param {*} target 原始对象
 * @param {*} type 进行操作类型
 * @param {*} key 针对哪一个属性
 */
export default function (target, type, key) {
  // 先进行开关状态的判断
  if (!shouldTrack || !activeEffect) {
    return
  }

  // 这里要做的事情其实和简单，就是一层一层的去找，找到了就存储
  let propMap = targetMap.get(target) // 获取对象和属性的映射关系
  if (!propMap) {
    // 创建对象和对象的属性的映射
    propMap = new Map()
    targetMap.set(target, propMap)
  }

  // 之前如果是遍历所有的属性，key 会是 undefined
  // 所以对 key 值做一下参数归一化处理
  if (type === TrackOpTypes.ITERATE) {
    key = ITERATE_KEY
  }

  // 获取属性 和 访问类型的映射关系
  let typeMap = propMap.get(key)
  if (!typeMap) {
    // 创建属性和访问类型的映射关系
    typeMap = new Map()
    propMap.set(key, typeMap)
  }

  // 最后一步，根据 type 值去找对应的 Set 函数依赖集合
  let depSet = typeMap.get(type)
  if (!depSet) {
    // 创建访问类型和依赖函数集合的映射关系
    depSet = new Set()
    typeMap.set(type, depSet)
  }

  // 现在找到 set 集合了，就可以存储依赖了
  if (!depSet.has(activeEffect)) {
    depSet.add(activeEffect)
    activeEffect.deps.push(depSet) // 将集合存储到 deps 数组里面，存储的是引用地址
  }
}
